using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace EventBehaviorTree
{
    [Serializable]
    public class FrameCounter : Container
    {
        private int _remainFrame;
        private int _duration;
        private int Duration { get => _duration; set => _duration = Mathf.Max(0, value); }
        protected WorkMode _workMode;
        public FrameCounter(WorkMode workMode, int duration,
            KeyValuePair<NodeMsg, NodeMsg>[] messagePairs, params NodeMsg[] silencedMessage) :
            base(messagePairs, silencedMessage)
        {
            _workMode = workMode;
            Duration = duration;
        }
        public FrameCounter(WorkMode workMode, int duration) : base()
        {
            _workMode = workMode;
            Duration = duration;
        }

        protected override IEnumerator Worker()
        {
            switch (_workMode)
            {
                case WorkMode.Async:
                case WorkMode.Busy:
                    _subNodes[0].NodeEvent(NodeMsg.Start);
                    break;
                case WorkMode.Delay:
                default:
                    break;
            }
            _remainFrame = Duration;
            while (_remainFrame > 0)//while the timer is working
            {
                yield return null;
                _remainFrame--;
            }
            switch (_workMode)
            {
                case WorkMode.Async:
                    StopAllSubNodes();//time up, stop the sub coroutine
                    _isWorking = false;
                    break;
                case WorkMode.Busy:
                    StopAllSubNodes();//time up, stop the sub coroutine
                    _isWorking = false;
                    SendMessage(NodeMsg.Succeed);
                    break;
                case WorkMode.Delay:
                    SendMessage(NodeMsg.Succeed); //just a timer
                    break;
                default:
                    break;
            }
            _asyncWorker.ResetWorker(Worker());
        }

        public override void NodeEvent(NodeMsg nodeMessage)
        {
            switch (nodeMessage)
            {
                case NodeMsg.Start:
                    if (!_isWorking)
                    {
                        StartWithEnumerator();
                        SendMessage(nodeMessage);
                    }
                    break;
                case NodeMsg.Succeed:
                    if (_stepCount < _subNodes.Count - 1)
                    {
                        _subNodes[++_stepCount].NodeEvent(NodeMsg.Start);
                        return;
                    }
                    switch (_workMode)//all successed
                    {
                        case WorkMode.Async:
                            SendMessage(nodeMessage);
                            break;
                        case WorkMode.Busy:
                        case WorkMode.Delay:
                        default:
                            break;
                    }
                    break;
                case NodeMsg.Fail:
                case NodeMsg.REQ_Abort:
                    StopWithEnumerator();
                    SendMessage(nodeMessage);
                    break;
                case NodeMsg.CMD_Stop:
                    if (_isWorking) StopWithEnumerator();
                    break;
                default:
                    break;
            }
        }
    }
}